package sharemem

import (
	"log"
	"server_cluster/battle/battle_config"
	"server_cluster/common/tools"
)

//状态定义
const (
    WEAK    =   1
    DEAD    =   2
    STUN    =   3
    FREEZE  =   4
    SILENT  =   5
    ARMOR   =   6
    FREE    =   7
    HERO    =   8
	TARGET	=	99

	VAL		=	1
	VAL_MAX =	2
	VAL_BUFF=	3
	VAL_INIT=	4
)

type Unit_attr struct {
	id			int32
	val			int32
	val_max		int32
	val_buff	int32
	val_init	int32
}

//生效条件已判断通过
type Skill_effect struct {
	trigger				*Battle_unit
	target				[]*Battle_unit
    begin_time          int32           //开始生效时间
    end_time            int32
	tag					int32
    params              *Cfg_skill_effect_params
}


type Skill_child struct {
    Type                int8            //技能类型
    effect              []*Skill_effect
}

//运行中的被动
type Skill_passive_pool struct {
	child			[]*Skill_child
	index			int8
}

//运行中的卡牌
type Skill_card_pool struct {
	tag				int8
    end_time        int32               //结束锁定真实时间 (结束锁定后，新卡牌可直接覆盖运行)
    child           []*Skill_child      //子技能组
    index           int8                //当前运行的子技能组下标 -1未运行
}

//效果参数配置
type Cfg_skill_effect_params struct {
    p1              [][]int32
    p2              map[int32]int32
	p3				int32
	p4				int32
	p5				int32
	p6				[]int32
}

//技能效果配置
type Cfg_skill_effect struct {
    target          int8
    ctype           bool
    condition       [][]int32
    begin_time      int32
    end_time        int32
	tag				int32
    params          *Cfg_skill_effect_params
}

//子技能配置
type Cfg_skill_child struct {
    Type            int8
    skill_effect    []*Cfg_skill_effect
}

//技能配置
type Cfg_skill struct {
	tag				int8
    cd_time         int32
    skill_child     []*Cfg_skill_child
}

//卡牌配置
type Cfg_skill_card struct {
    id              int32
    target          int8
    tag             int8
    weight          int32
    skill1          *Cfg_skill
    skill2          *Cfg_skill
    skill3          *Cfg_skill
}

//序列配置
type Cfg_order  struct {
    skill_card      *Cfg_skill_card
    time            int32
}

//被动技能配置
type Cfg_skill_passive struct {
	id				int32				//被动id
	cd_time			int32				//cd time
    begin_time		int32				//可触发时间
	skill_child		[]*Cfg_skill_child	//配置

	pool			*Skill_passive_pool	//运行池子
}

type Card_weight struct {
	id				int32
	weight			int32
}

type Battle_unit struct {
	area				*Battle_area									//战场指针
    id                  int32
	index				int8											//单位数组下标
    Type                int8                                            //单位类型(1 怪物 2 上阵角色 3 支援角色)
    tag					int8											//单位tag(怪物：1 小怪 2 精英 3 BOSS) 或 (角色：1火 2冰 3风 4暗)
    weak                []int8                                          //弱点组
    ex_card             *Cfg_skill_card                                 //大招卡牌
    order               []*Cfg_order                                    //序列时间组
    normal_card			map[int32]*Cfg_skill_card						//普通卡牌map
	card_weight			[]*Card_weight									//普通卡牌顺序组

    order_max           int8                                            //order总数
    order_index         int8                                            //当前order位置
    order_time          int32                                           //order可执行主轴时间

	tough_time			int32											//韧性值回满主轴时间(0不生效)

    at                  map[int32]*Unit_attr                            //属性id:Unit_attr指针
    passive             map[int8]*[]*Cfg_skill_passive					//触发点:Cfg_skill_passive组
	run_passive			[]*Cfg_skill_passive							//被动技能顺序数组

    draw_card           map[int32]int8                                  //手牌卡id:数量

    state               map[int8]int8                                   //全部状态 id:数量
    buff	            map[int8]map[int32]*Buff_have					//Sub_type:group_id:Buff_have指针
	shield				[]int32											//盾group_id有序组
	undead				[]int32											//免死group_id有序组
    run_card            *Skill_card_pool                                //正在运行中的卡牌 仅支持一种卡牌运行 end_time之后，允许切换新卡牌(老卡牌剩余效果全部撤消删除)
	stop_time			int32											//被控主轴时间戳(解控使用) -1表示没有被控
}

func (u *Battle_unit)GetNormalCardMap() map[int32]*Cfg_skill_card {
    if u.normal_card == nil {
        u.normal_card = make(map[int32]*Cfg_skill_card,UNIT_NORMAL_CARD_MAX)
    }
    return u.normal_card
}

func (u *Battle_unit)GetAllPassiveMap() map[int8]*[]*Cfg_skill_passive {
    if u.passive == nil {
        u.passive = make(map[int8]*[]*Cfg_skill_passive,UNIT_PASSIVE_MAX)
    }
    return u.passive
}

func (u *Battle_unit)GetPassiveMap(trigger int8) *[]*Cfg_skill_passive {
    tmp := u.GetAllPassiveMap()
    if tmp[trigger] == nil {
        tt := make([]*Cfg_skill_passive,0)
		tmp[trigger] = &tt
    }
    return tmp[trigger]
}

func (u *Battle_unit)GetAllBuffMap() map[int8]map[int32]*Buff_have {
	if u.buff == nil {
		u.buff = make(map[int8]map[int32]*Buff_have,UNIT_BUFF_MAX)	//1 修改属性、2 伤害、3 治疗、4 晕眩、5 冰冻、6 沉默、7 霸体、8 免疫控制、9 无敌、10 免死、11 护盾
	}
	return u.buff
}

func (u *Battle_unit)GetBuffMap(sub_type int8) map[int32]*Buff_have {
	tmp:=u.GetAllBuffMap()
	if tmp[sub_type] == nil {
		tmp[sub_type] = make(map[int32]*Buff_have,UNIT_BUFF_MAX)
	}
	return tmp[sub_type]
}

func (u *Battle_unit)GetAtMap() map[int32]*Unit_attr {
    if u.at == nil {
        u.at = make(map[int32]*Unit_attr,UNIT_ATTR_MAX)
    }
    return u.at
}

func (u *Battle_unit)GetDrawCardMap() map[int32]int8 {
    if u.draw_card == nil {
        u.draw_card = make(map[int32]int8,battle_config.CARD_NUM_MAX)
    }
    return u.draw_card
}

func (u *Battle_unit)GetStateMap() map[int8]int8 {
    if u.state == nil {
        u.state = make(map[int8]int8,UNIT_STATE_MAX)
    }
    return u.state
}

//存在当前值的属性是否空
func (a *Unit_attr)IsEmpty() bool {
	return a.GetValByType(VAL) == 0
}

//存在当前值的属性是否满
func (a *Unit_attr)IsFull() bool {
	val := a.GetValByType(VAL)
	return val > 0 && val == a.GetValByType(VAL_MAX)
}

//通过type获取属性最终值
func (a *Unit_attr)GetValByType(Type int8) int32 {
	val := int32(0)
	if a.id == HP || a.id == ANGER || a.id == TOUGH || a.id == FREEZEVALUE {
		switch Type {
			case VAL:
				val = a.GetValByType(VAL_MAX)
				//不能超过最大值
				if val > a.val {
					val = a.val
				}
			case VAL_INIT:
				val = a.val_init
			case VAL_BUFF:
				val = a.val_buff
			default:
				val = a.val_max + a.val_buff
				if val < 0 {
					val = 0
				}
		}
	} else {
		switch Type {
			case VAL_INIT:
				val = a.val_init
			case VAL_BUFF:
				val = a.val_buff
			default:
				val = a.val_max + a.val_buff
				if val < 0 {
					val = 0
				}
		}
	}
	return val
}

//更新属性 val 0表示清空
func (a *Unit_attr)UpdateValue(Type int8,val int32) {
	switch Type {
		case VAL:
			val_max := a.val_max + a.val_buff
			if val_max < 0 {
				val_max = 0
			}
			if a.id == ANGER && a.val == val_max && val != 0{
				return
			}
			a.val += val
			if a.val < 0 || val == 0 {
				a.val = 0
			} else if a.val > val_max {
				a.val = val_max
			}
		case VAL_MAX:
			a.val_max += val
			if a.val_max < 0 || val == 0{
				a.val_max = 0
			}
			//
		case VAL_BUFF:
			a.val_buff += val
	}
}

//控制
func (u *Battle_unit)Control() {
	if u.IsControl() {
		return
	}
	u.stop_time = u.area.root_time
}
//解控
func (u *Battle_unit)DeControl() {
	if !u.IsControl() {
		return
	}
	//序列恢复
	u.order_time += (u.area.root_time - u.stop_time)
	u.stop_time = -1
}

//设置状态 
func (u *Battle_unit)SetState(id int8,num int8) {
	smap := u.GetStateMap()
	if num == 0 {
		//直接清空
		smap[id] = 0
	} else {
		smap[id] += num
		if smap[id] < 0 {
			smap[id] = 0
		}
	}

	if u.TakeState(id) {
		//生效
		switch id {
			case STUN:
				//晕
				//打断技能
				u.KillSkill(true)
				u.Control()
			case FREEZE:
				//冰冻
				//打断技能
				u.KillSkill(true)
				u.Control()
			case SILENT:
				//沉默
				//打断除普攻的技能
				u.KillSkill(false)
			case FREE:
				//免控
				//清除sub_buff
				u.ClearBuff(2,4,0,0)
				u.ClearBuff(2,5,0,0)
				u.ClearBuff(2,6,0,0)
				u.DeControl()
			case HERO:
				//无敌
				//清除debuff
				u.ClearBuff(1,2,0,0)
				u.DeControl()
			case ARMOR:
				//霸体
				u.DeControl()
		}
	} else {
		//失效
		if id == TARGET && !u.IsHealthy(){
			//受击结束 且 血量为0
			u.SetState(DEAD,1)
		}
		if u.CheckControlState() {
			//打断技能
			u.KillSkill(true)
			u.Control()
		} else {
			u.DeControl()
		}
	}
}

//获取指定生效状态
func (u *Battle_unit)TakeState(id int8) bool {
	smap := u.GetStateMap()
	//免控、无敌、霸体生效 使 晕眩、冰冻、沉默无法生效
	if (id == STUN || id == FREEZE || id == SILENT) && (smap[FREE] > 0 || smap[HERO] > 0 || smap[ARMOR] > 0){
		return false
	}
	return smap[id] > 0
}
//是否被控制
func (u *Battle_unit)CheckControlState() bool {
	for _,v := range u.TakeAllState() {
		if v == STUN || v == FREEZE {
			return true
		}
	}
	return false
}

func (u *Battle_unit)IsControl() bool {
	return u.stop_time >= 0
}

//获取所有生效的状态集
func (u *Battle_unit)TakeAllState() []int8 {
	state := make([]int8,0)
	smap := u.GetStateMap()
	if smap[DEAD] > 0 {
		state = append(state,DEAD)
	}
	if smap[WEAK] > 0 {
		state = append(state,WEAK)
	}
	if smap[FREE] > 0 {
		state = append(state,FREE)
	}
	if smap[HERO] > 0 {
		state = append(state,HERO)
	}
	if smap[ARMOR] > 0 {
		state = append(state,ARMOR)
	}
	//免控、无敌、霸体生效 使 晕眩、冰冻、沉默无法生效
	if smap[FREE] > 0 || smap[HERO] > 0 || smap[ARMOR] > 0 {
		return state
	}
	if smap[STUN] > 0 {
		state = append(state,STUN)
	}
	if smap[FREEZE] > 0 {
		state = append(state,FREEZE)
	}
	if smap[SILENT] > 0 {
		state = append(state,SILENT)
	}
	return state
}

//是否存在
func (u *Battle_unit)Exist() bool {
	if u == nil {
		return false
	}
	return u.id > 0
}
//是否存活状态
func (u *Battle_unit)Alive() bool {
	if !u.Exist() {
		return false
	}
	return !u.TakeState(DEAD)
}
//hp是否大于0
func (u *Battle_unit)IsHealthy() bool {
	if !u.Exist() {
		return false
	}
	return u.TakeAtVal(VAL,HP) > 0
}

//定期恢复怒气
func (u *Battle_unit)RageAddByTime() {
	num := u.TakeAtVal(VAL_MAX,CHARGE) * u.TakeAtVal(VAL_MAX,EXCHARGE) / 10000
	if num <= 0 {
		return
	}
    u.ChangeAttr(VAL,ANGER,num)
}
//检查卡牌是否足够
func (u *Battle_unit)CardEnough(id int32,num int8) bool {
	return u.GetDrawCardMap()[id] >= num
}
//随机抽卡
func (u *Battle_unit)DrawCard(num int) {
	if num <= 0 {
		return
	}
	total := int32(0)
	for _,v := range u.card_weight {
		if v.id <= 0 {
			continue
		}
		total += v.weight
	}

	if total == 0 {
		return
	}
	for i:=0;i<num; {
		w := tools.MyRand(0,total)
		for _,v := range u.card_weight {
			if w < v.weight {
				u.ChangeCard(v.id,1)
				i++
				break
			}
			w -= v.weight
		}
	}
}

//更改卡牌数量
func (u *Battle_unit)ChangeCard(id int32,num int8) {
	u.GetDrawCardMap()[id] += num
}

//伤害扣盾值 返回剩余伤害
func (u *Battle_unit)DoShield(num int32) int32 {
	if num >= 0 {
		return num
	}
	all := u.GetBuffMap(BUFF_SUB_TYPE_SHIELD)
	if len(all) <= 0 {
		return num
	}

	del := make([]int,0)
	for k,v := range u.shield {
		buff := all[v]
		if buff == nil {
			log.Printf("do shield buff group id %d error.",v)
			del = append(del,k)
			continue
		}
		if buff.total + num > 0 {
			buff.total += num
			return 0
		} else {
			num += buff.total
			//清除此buff
			u.BuffEndEvent(buff)
			delete(all,buff.group)
			del = append(del,k)
		}
	}
	for _,v := range del {
		u.shield = tools.Remove(u.shield,v)
	}
	return num
}
//免死buff生效
func (u *Battle_unit)DoUnDead() int32 {
	hp_add := int32(0)
	all := u.GetBuffMap(BUFF_SUB_TYPE_UNDEAD)
	if len(all) <= 0 {
		return hp_add
	}
	del := make([]int,0)
	for k,v := range u.undead {
		buff := all[v]
		if buff == nil {
			log.Printf("do undead buff group id %d error.",v)
			del = append(del,k)
			continue
		}
		buff.level--
		//回血量
		hp_add = buff.total
		if buff.level <= 0 {
			u.BuffEndEvent(buff)
			delete(all,buff.group)
			del = append(del,k)
		}
		//仅需生效一个免死buff
		break
	}
	for _,v := range del {
		u.undead = tools.Remove(u.undead,v)
	}
	return hp_add
}

//伤害治疗 血量当前值
func (u *Battle_unit)DoHP(num int32) {
	//log.Printf("do hp type=%d site=%d",u.Type,u.index)
	if u.Type == UNIT_TYPE_ROLE_ASSIST {
		return
	}
	if num == 0 {
        log.Printf("change attr HP num %d.",num)
		return
	} else if num > 0 {
		if u.TakeAtVal(VAL,HP) == 0 {
			log.Printf("血量为0 无法加血")
			return
		}
	} else {
		if u.TakeState(HERO) {
			//无敌状态 无法扣血
			return
		}
	}
	if num < 0 {
		u.PassiveStart(u,POS_ME_DMG)
		if len(u.shield) > 0 {
			//先扣护盾值
			num = u.DoShield(num)
			if num == 0 {
				return
			}
		}
	}

	hp_max := u.TakeAtVal(VAL_MAX,HP)
	hp_val := u.ChangeAttr(VAL,HP,num)
	//
	if hp_val == 0	{
		//免死buff生效 并加血
		hp_val = u.ChangeAttr(VAL,HP,u.DoUnDead())
	}
	if hp_val == 0 {
		//特殊处理 血量上限归0
		hp_max = u.ChangeAttr(VAL_MAX,HP,0)
		//打断自己的技能
		u.KillSkill(true)
		if !u.Alive() {
			var i int8
			switch u.Type {
				case UNIT_TYPE_MONSTER:
					for i=0;i<BATTLE_MONSTER;i++ {
						if !u.area.monster[i].Alive() {
							continue
						}
						u.area.monster[i].PassiveStart(u,POS_MY_DEAD)
					}
				case UNIT_TYPE_ROLE:
					for i=0;i<BATTLE_ROLE;i++ {
						if !u.area.role[i].Alive() {
							continue
						}
						u.area.role[i].PassiveStart(u,POS_MY_DEAD)
					}
					for i=0;i<BATTLE_ROLE_ASSIST;i++ {
						if !u.area.role_assist[i].Alive() {
							continue
						}
						u.area.role_assist[i].PassiveStart(u,POS_MY_DEAD)
					}
			}
		}
	}

	if hp_val > 0 && hp_val < hp_max/5 {
		//设置为虚弱状态
		u.SetState(WEAK,1)
	} else {
		//清除虚弱状态
		u.SetState(WEAK,0)
	}
}

//冰冻值操作
func (u *Battle_unit)DoFreeze(num int32) {
	if u.Type == UNIT_TYPE_ROLE_ASSIST {
		return
	}
	if num <= 0 {
		log.Printf("change freeze num %d.",num)
		return
	}
	if u.TakeState(FREEZE) {
		return
	}
	u.ChangeAttr(VAL,FREEZEVALUE,num)
}

func (u *Battle_unit)TakeAtVal(Type int8,id int32) int32 {
	attr := u.GetAtMap()[id]
	if attr == nil {
		log.Printf("TakeAtVal attr %d is not found.",id)
		return 0
	}
	return attr.GetValByType(Type)
}

//num:0 表示直接清空 固定返回最新最终值
func (u *Battle_unit)ChangeAttr(Type int8,id int32,num int32) int32 {
	attr := u.GetAtMap()[id]
	if attr == nil {
		log.Printf("ChangeAttr attr %d is not found.",id)
		return 0
	}
	old_val := attr.GetValByType(VAL)
	attr.UpdateValue(Type,num)
	new_val := attr.GetValByType(VAL)
	//变化量
	change_val := new_val - old_val
	log.Printf("change attr Type=%d id=%d new_val=%d change=%d",Type,id,new_val,change_val)
	if change_val == 0 {
		return new_val
	}
	//属性变动业务
	switch id {
		case HP:
			if change_val < 0 {
				//受伤回怒气
				hp_max := u.TakeAtVal(VAL_MAX,HP)
				if hp_max == 0 {
					return new_val
				}
				drage := u.TakeAtVal(VAL_MAX,DRAGE)
				charge := u.TakeAtVal(VAL_MAX,CHARGE)
				anger := u.TakeAtVal(VAL_MAX,ANGER)
				rage := -change_val*drage*anger/10000*charge/10000/hp_max
				if rage > 0 {
					u.ChangeAttr(VAL,ANGER,rage)
				}
			}
			//被动
			u.PassiveStart(u,POS_ME_ATTR_HP)
		case TOUGH:
			if new_val == 0 {
				//破韧
				u.tough_time = u.area.root_time + battle_config.MONSTER_TOUGHTIME
				for _,v := range tools.String2Array(battle_config.MONSTER_TOUGHBUFF,"|") {
					u.AddBuff(u,v,1)
				}
				//被动
				u.PassiveStart(u,POS_ME_ATTR_TOUGH_0)
				var i int8
				for i=0;i<BATTLE_ROLE;i++ {
					if !u.area.role[i].Alive() {
						continue
					}
					u.area.role[i].PassiveStart(u,POS_OTHER_ATTR_TOUGH_0)
				}
				for i=0;i<BATTLE_ROLE_ASSIST;i++ {
					if !u.area.role_assist[i].Alive() {
						continue
					}
					u.area.role_assist[i].PassiveStart(u,POS_OTHER_ATTR_TOUGH_0)
				}
			}
		case ANGER:
		case SPEED:
			//被动
			u.PassiveStart(u,POS_ME_ATTR_SPEED)
		case FREEZEVALUE:
			if attr.IsFull() {
				//已满
				freeze := tools.String2Array(battle_config.FREEZE,"|")
				if len(freeze) != 2 {
					log.Printf("attr freezevalue config error.")
					break
				}
				u.AddBuff(u,freeze[1],1)
				//直接清空
				attr.UpdateValue(Type,0)
			}
		default:
	}
	return new_val
}

func (u *Battle_unit)DoPassive(Type int8) {
	switch Type {
		case 0:
			u.PassiveStart(u,POS_GAME_BEGIN)
		case 1:
			u.PassiveStart(u,POS_CD_TIME)
		case 2:
			u.PassiveStart(u,POS_DRAW_CARD)
	}
}

func (u *Battle_unit)ResetUnitData() {
	//清空buff
	u.buff = nil
	u.shield = make([]int32,0)
	u.undead = make([]int32,0)
	//清空正在进行的技能
	u.KillSkill(true)
	u.run_passive = nil
	//清空状态
	u.state = nil
}
